package cn.gjsm.controller;

import cn.gjsm.pojos.OpenAi;
import cn.gjsm.pojos.OpenAiExt;
import cn.gjsm.pojos.resultVO.R;
import cn.gjsm.utils.JSONUtil;
import cn.gjsm.utils.OpenAiClient;
import cn.gjsm.utils.SessionUtil;
import cn.gjsm.utils.SpecificScenariosUtil;
import com.theokanning.openai.completion.CompletionChoice;
import com.theokanning.openai.model.Model;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/openai")
public class OpenAiController {
    @Autowired
    HttpServletRequest request;
    @Autowired
    HttpServletResponse response;

    @GetMapping("/scene-list")
    public R<Collection<OpenAi>> sceneList() {
        List<OpenAi> collect = SpecificScenariosUtil.PARMS.values().stream()
                .sorted(Comparator.comparing(OpenAi::getId))
                .collect(Collectors.toList());
        return R.data(collect);
    }

    @GetMapping("/request")
    public R<List<CompletionChoice>> request(@RequestParam("id") String id,
        @RequestParam(value = "question")String question,
        @RequestParam(value = "timestamp", required = false) String timestamp,
        @RequestParam(value = "empNo", required = false)String empNo
    ){
        log.info("requestUrl:{}, currentTime:{}", request.getRequestURI() + request.getQueryString());
        log.info("requestParam(clientTime,empNo,id,question): {},{},{},{}", timestamp, empNo, id, question);

        OpenAi defaultOpenAi = SpecificScenariosUtil.PARMS.get("OpenAi01");
        var aiOp = SpecificScenariosUtil.PARMS.values().stream()
                .filter(t -> StringUtils.equalsIgnoreCase(t.getId(), id))
                .findFirst();
        var openAi = aiOp.orElseGet(() -> defaultOpenAi);

        var start = System.currentTimeMillis();
        var service = SessionUtil.getAiService(request, response);
        var response = OpenAiClient.getAiResult(service, openAi, String.format(openAi.getPrompt(), question));
        var end = System.currentTimeMillis();
        var timeConsuming = end - start;

        log.info("openAiStat(empNo,clientTime,startReq,endReq,processTimeConsuming,word,return):{},{},{},{},{},{},{}", empNo, timestamp, start, end, timeConsuming, question, JSONUtil.toFormatedJson(response));
        return R.data(response);
    }


    @PostMapping("/request")
    public R<List<CompletionChoice>> request(@RequestBody OpenAiExt openAiExt){
        log.info("requestParamOpenAiExt: {}", JSONUtil.toFormatedJson(openAiExt));

        OpenAi openAi = null;
        String prompt = null;
        if(!openAiExt.isClientAiParam()){
            OpenAi defaultOpenAi = SpecificScenariosUtil.PARMS.get("OpenAi01");
            var aiOp = SpecificScenariosUtil.PARMS.values().stream()
                    .filter(t -> StringUtils.equalsIgnoreCase(t.getId(), openAiExt.getId()))
                    .findFirst();
            openAi = aiOp.orElseGet(() -> defaultOpenAi);
            prompt = String.format(openAi.getPrompt(), openAiExt.getPrompt());
        }else{
            openAi = openAiExt;
            prompt = openAiExt.getPrompt();
        }

        var start = System.currentTimeMillis();
        var service = SessionUtil.getAiService(request, response);
        var response = OpenAiClient.getAiResult(service, openAi, prompt);
        var end = System.currentTimeMillis();
        var timeConsuming = end - start;

        log.info("openAiStat(empNo,clientTime,startReq,endReq,processTimeConsuming,word,return):{},{},{},{},{},{},{}", openAiExt.getEmpNo(), openAiExt.getTimestamp(), start, end, timeConsuming, openAiExt.getPrompt(), JSONUtil.toFormatedJson(response));
        return R.data(response);
    }




    /*
    void otherModel(){
        CompletionRequest completionRequest = CompletionRequest.builder()
                .model("ada")
                .prompt("Somebody once told me the world is gonna roll me")
                .echo(true)
                .n(5)
                .maxTokens(50)
                .user("testing")
                .logitBias(new HashMap<>())
                .build();

        var service = OpenAiUtils.getOpenAiService();
        List<CompletionChoice> choices = service.createCompletion(completionRequest).getChoices();
        assertEquals(5, choices.size());
    }
    */

    @GetMapping("/list-models")
    public R<List<Model>> listModels(){
        var service = OpenAiClient.getOpenAiService();
        List<Model> models = service.listModels();

        return R.data(models);
    }


    @GetMapping("/token")
    public R<String> token(){
       return R.data(OpenAiClient.OPENAPI_TOKEN);
    }

    @PostMapping("/token")
    public R<String> token(
            @RequestParam(value = "token", required = false)String token
    ){
        OpenAiClient.OPENAPI_TOKEN = token;

        //clean cache
        SessionUtil.cleanCache();
        return R.data(OpenAiClient.OPENAPI_TOKEN);
    }

}